package com.dynamic.mybatis.core.generator.helper;

import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
import com.dynamic.mybatis.core.generator.InjectorHelper;
import com.dynamic.mybatis.core.metadata.MappedStatementField;
import com.dynamic.mybatis.core.metadata.MappedStatementMetaField;
import com.dynamic.mybatis.core.metadata.MappedStatementTable;

import java.util.Objects;
import java.util.Optional;

import static java.util.stream.Collectors.joining;

/**
 * @Description
 * @Author xs
 * @Date 2023/4/14 13:55
 */
public class InsertInjectorHelper extends InjectorHelper {

    /**
     * 获取 insert 时候字段 sql 脚本片段
     * <p>insert into table (字段) values (值)</p>
     * <p>位于 "字段" 部位</p>
     *
     * <li> 自动选部位,根据规则会生成 if 标签 </li>
     *
     * @return sql 脚本片段
     */
    public static String getAllInsertSqlColumnMaybeIf(MappedStatementTable table, final String prefix) {
        final String newPrefix = prefix == null ? EMPTY : prefix;
        return getKeyInsertSqlColumn(table,false, false) +NEWLINE+ table.getFields().stream()
                .filter(f -> !f.isPrimaryKey())
                .map(f -> InsertInjectorHelper.getInsertSqlColumnMaybeIf(f,newPrefix))
                .filter(Objects::nonNull).collect(joining(NEWLINE));
    }

    /**
     * 获取所有 insert 时候插入值 sql 脚本片段
     * <p>insert into table (字段) values (值)</p>
     * <p>位于 "值" 部位</p>
     *
     * <li> 自动选部位,根据规则会生成 if 标签 </li>
     *
     * @return sql 脚本片段
     */
    public static String getAllInsertSqlPropertyMaybeIf(MappedStatementTable table,final String prefix) {
        final String newPrefix = prefix == null ? EMPTY : prefix;
        return getKeyInsertSqlProperty(table,false, newPrefix, false) +NEWLINE+ table.getFields().stream()
                .filter(f -> !f.isPrimaryKey())
                .map(i -> InsertInjectorHelper.getInsertSqlPropertyMaybeIf(i,newPrefix))
                .filter(Objects::nonNull).collect(joining(NEWLINE));
    }



    /**
     * 获取 insert 时候字段 sql 脚本片段
     * <p>insert into table (字段) values (值)</p>
     * <p>位于 "字段" 部位</p>
     *
     * <li> 根据规则会生成 if 标签 </li>
     *
     * @return sql 脚本片段
     */
    public static String getInsertSqlColumnMaybeIf(MappedStatementField field, final String prefix) {
        final String newPrefix = prefix == null ? EMPTY : prefix;
        final String sqlScript = getInsertSqlColumn(field.getColumn());
        if (withInsertFill) {
            return sqlScript;
        }
        return convertIf(field,sqlScript, newPrefix + field.getField(), insertStrategy);
    }

    /**
     * 获取 insert 时候插入值 sql 脚本片段
     * <p>insert into table (字段) values (值)</p>
     * <p>位于 "值" 部位</p>
     *
     * <li> 根据规则会生成 if 标签 </li>
     *
     * @return sql 脚本片段
     */
    public static String getInsertSqlPropertyMaybeIf(MappedStatementField field,final String prefix) {
        final String newPrefix = prefix == null ? EMPTY : prefix;
        String sqlScript = getInsertSqlProperty(field,newPrefix);
        if (withInsertFill) {
            return sqlScript;
        }
        return convertIf(field,sqlScript, newPrefix + field.getField(), insertStrategy);
    }

    /**
     * 获取 insert 时候字段 sql 脚本片段
     * <p>insert into table (字段) values (值)</p>
     * <p>位于 "字段" 部位</p>
     *
     * <li> 不生成 if 标签 </li>
     *
     * @return sql 脚本片段
     */
    public static String getInsertSqlColumn(String column) {
        return column + COMMA;
    }

    /**
     * 获取 insert 时候插入值 sql 脚本片段
     * <p>insert into table (字段) values (值)</p>
     * <p>位于 "值" 部位</p>
     *
     * <li> 不生成 if 标签 </li>
     *
     * @return sql 脚本片段
     */
    public static String getInsertSqlProperty(MappedStatementField field,final String prefix) {
        final String newPrefix = prefix == null ? EMPTY : prefix;
        return SqlScriptUtils.safeParam(newPrefix + field.getField()) + COMMA;
    }


    /**
     * 获取 insert 时候主键 sql 脚本片段
     * <p>insert into table (字段) values (值)</p>
     * <p>位于 "字段" 部位</p>
     *
     * @return sql 脚本片段
     */
    public static String getKeyInsertSqlColumn(MappedStatementTable table,final boolean batch, final boolean newLine) {
        Optional<MappedStatementMetaField> optionalField;
        if ((optionalField = getFirstKeyField(table)).isPresent()) {
            MappedStatementField field = optionalField.get();
            if (field.isAutoincrement()) {
                if (batch) {
                    // 批量插入必须返回空自增情况下
                    return EMPTY;
                }
                return SqlScriptUtils.convertIf(field.getColumn() + COMMA, String.format("%s != null", field.getField()), newLine);
            }
            return field.getColumn() + COMMA + (newLine ? NEWLINE : EMPTY);
        }
        return EMPTY;
    }


    /**
     * 获取 insert 时候主键 sql 脚本片段
     * <p>insert into table (字段) values (值)</p>
     * <p>位于 "值" 部位</p>
     *
     * @return sql 脚本片段
     */
    public static String getKeyInsertSqlProperty(MappedStatementTable table,final boolean batch, final String prefix, final boolean newLine) {
        final String newPrefix = prefix == null ? EMPTY : prefix;
        Optional<MappedStatementMetaField> optionalField;
        if ((optionalField = getFirstKeyField(table)).isPresent()) {
            final String prefixKeyProperty = newPrefix + optionalField.get().getField();
            String keyColumn = SqlScriptUtils.safeParam(prefixKeyProperty) + COMMA;
            if (optionalField.get().isAutoincrement()) {
                if (batch) {
                    // 批量插入必须返回空自增情况下
                    return EMPTY;
                }
                return SqlScriptUtils.convertIf(keyColumn, String.format("%s != null", prefixKeyProperty), newLine);
            }
            return keyColumn + (newLine ? NEWLINE : EMPTY);
        }
        return EMPTY;
    }

}